package main

import (
	"bytes"
	_ "embed"
	"fmt"
	"os"
	"path/filepath"
	"sort"
	"text/template"
)

//go:embed template.mk
var tmplData string

var tmpl = template.Must(template.New("main").Parse(tmplData))

type Tool struct {
	Name     string
	Dir      string
	Flags    string
	Deps     string
	ProdDeps string
}

type Build struct {
	Name string
	Env  string
	Ext  string
}
type Bundle struct {
	Name     string
	CopyDir  []string
	SubDir   string
	Binaries []string
}

func (b Bundle) DirName() string {
	if b.SubDir != "" {
		return b.SubDir
	}
	return b.Name
}

func newTool(path string) Tool {
	dir := filepath.Dir(path)
	return Tool{
		Name: filepath.Base(dir),
		Dir:  dir,
	}
}

func main() {
	var data struct {
		Tools         []Tool
		Builds        []Build
		Bundles       []Bundle
		ContainerArch []string
	}

	data.ContainerArch = []string{"amd64", "arm", "arm64"}

	data.Builds = []Build{
		{Name: "linux-amd64", Env: "GOOS=linux GOARCH=amd64"},
		{Name: "linux-arm", Env: "GOOS=linux GOARCH=arm GOARM=7"},
		{Name: "linux-arm64", Env: "GOOS=linux GOARCH=arm64"},
		{Name: "darwin-amd64", Env: "GOOS=darwin GOARCH=amd64"},
		{Name: "windows-amd64", Env: "GOOS=windows GOARCH=amd64", Ext: ".exe"},
	}
	data.Bundles = []Bundle{
		{Name: "goalert", Binaries: []string{
			"goalert",
			"goalert-slack-email-sync",
		}},
	}

	files, err := filepath.Glob("./cmd/*/main.go")
	if err != nil {
		panic(err)
	}
	for _, t := range files {
		tool := newTool(t)
		if tool.Name == "goalert" {
			tool.Flags = `-ldflags "$(LD_FLAGS)"`
			tool.Deps = "graphql2/mapconfig.go"
			tool.ProdDeps = "web/src/build/static/app.js"
		}
		data.Tools = append(data.Tools, tool)
	}

	sort.Slice(data.Tools, func(i, j int) bool { return data.Tools[i].Name < data.Tools[j].Name })
	sort.Slice(data.Builds, func(i, j int) bool { return data.Builds[i].Name < data.Builds[j].Name })

	var buf bytes.Buffer
	err = tmpl.Execute(&buf, data)
	if err != nil {
		panic(err)
	}
	fmt.Print("# Code generated by devtools/genmake, DO NOT EDIT.\n\n")
	if _, err = buf.WriteTo(os.Stdout); err != nil {
		panic(err)
	}
}
